package cn.hlife.com.hlfhaemocyte.view;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.graphics.Typeface;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;


import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cn.hlife.com.hlfhaemocyte.utils.DisplayUtil;

/**
 * @author Administrator
 * 
 */
public class WaterWaveProgress extends View {
	private Paint mPaintWater = null, mRingPaint = null, mTextPaint = null;
	private int mRingColor, mRingBgColor, mWaterColor, mWaterBgColor,
			mFontSize, mTextColor;
	float  crestCount = 1.5f;
	
	int mProgress = 0, mMaxProgress = 100;

	private ExecutorService threadPool;
	private Point mCenterPoint;
	private float mRingWidth, mProgress2WaterWidth;
	private boolean mShowProgress = true, mShowNumerical = true;

	private long mWaveFactor = 0L;
	private boolean isWaving = false;
	private float mAmplitude = 30.0F;
	private float mWaveSpeed = 0.050F;
	private int mWaterAlpha = 255; // 255
	WaterWaveAttrInit attrInit;

	private MyHandler mHandler = null;
	private Paint arcLinePaint;
	private int paintWidth;
	private int mTextSize;
	private PaintFlagsDrawFilter mSetfil;
	private Typeface typeFace;
	private int valueB;
	private int mCurrentProgress;

	private static class MyHandler extends Handler {
		private WeakReference<WaterWaveProgress> mWeakRef = null;

		private int refreshPeriod = 100;

		public MyHandler(WaterWaveProgress host) {
			mWeakRef = new WeakReference<WaterWaveProgress>(host);
		}

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			if (mWeakRef.get() != null) {
				mWeakRef.get().invalidate();
				sendEmptyMessageDelayed(0, refreshPeriod);
			}
		}
	}

	public WaterWaveProgress(Context paramContext) {
		super(paramContext);
	}

	public WaterWaveProgress(Context context, AttributeSet attributeSet) {
		this(context, attributeSet, 0);
	}

	public WaterWaveProgress(Context context, AttributeSet attrs,
                             int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		attrInit = new WaterWaveAttrInit(context, attrs, defStyleAttr);
		threadPool = Executors.newSingleThreadExecutor();
		init(context);
	}


	private void init(Context context) {
		AssetManager assetManager = context.getAssets();
		typeFace = Typeface.createFromAsset(assetManager, "fonts/HelveticaNeue-Thin.ttf");
		mSetfil = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG| Paint.FILTER_BITMAP_FLAG| Paint.DITHER_FLAG);
		mCenterPoint = new Point();
		mRingColor = attrInit.getProgressColor();
		mRingBgColor = attrInit.getProgressBgColor();
		mWaterColor = attrInit.getWaterWaveColor();
		mWaterBgColor = attrInit.getWaterWaveBgColor();
		mRingWidth = attrInit.getProgressWidth();
		mProgress2WaterWidth = attrInit.getProgress2WaterWidth();
		mShowProgress = attrInit.isShowProgress();
		mShowNumerical = attrInit.isShowNumerical();
		mFontSize = attrInit.getFontSize();
		mTextColor = attrInit.getTextColor();
		mProgress = attrInit.getProgress();
		mMaxProgress = attrInit.getMaxProgress();

		// 如果手机版本在4.0以上,则开启硬件加速
		if (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) {
//			setLayerType(View.LAYER_TYPE_HARDWARE, null);
			 setLayerType(View.LAYER_TYPE_SOFTWARE, null);
		}
		paintWidth = DisplayUtil.dip2px(context, 4);
		mTextSize = DisplayUtil.dip2px(context, 15);
		valueB = DisplayUtil.dip2px(context, 1);

		mRingPaint = new Paint();
		mRingPaint.setAntiAlias(true);
		mRingPaint.setColor(mRingColor); // 圆环颜色
		mRingPaint.setStyle(Paint.Style.STROKE);
		mRingPaint.setStrokeWidth(mRingWidth); // 圆环宽度

		mPaintWater = new Paint();
		mPaintWater.setStrokeWidth(1.0F);
		mPaintWater.setColor(mWaterColor);
		// mPaintWater.setColor(getResources().getColor(mWaterColor));
		mPaintWater.setAlpha(mWaterAlpha);

		mTextPaint = new Paint();
		mTextPaint.setAntiAlias(true);
		mTextPaint.setDither(true);
		mTextPaint.setColor(mTextColor);
		mTextPaint.setStyle(Paint.Style.FILL);
		mTextPaint.setTextSize(mTextSize);
		mTextPaint.setTypeface(typeFace);
		mHandler = new MyHandler(this);


		arcLinePaint = new Paint();
		arcLinePaint.setStrokeWidth(paintWidth);
		arcLinePaint.setAntiAlias(true);
		arcLinePaint.setStyle(Paint.Style.STROKE);
		arcLinePaint.setDither(true);
		arcLinePaint.setColor(0xFFe4e3e8);

	}

	public void animateWave() {
		if (!isWaving) {
			mWaveFactor = 0L;
			isWaving = true;
			mHandler.sendEmptyMessage(0);
		}
	}

	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// 获取整个View（容器）的宽、高
		canvas.setDrawFilter(mSetfil);
		int width = getWidth();
		int height = getHeight();
		width = height = (width < height) ? width : height;
		mAmplitude = width / 20f;

		int radius=(int)(width/2*0.85);

		int centerX=width/2;
		int centerY=height/2;

		mCenterPoint.x = width / 2;
		mCenterPoint.y = height / 2;
		{ // 重新设置进度条的宽度和水波与进度条的距离,,至于为什么写在这,我脑袋抽了可以不
			mRingWidth = mRingWidth == 0 ? width / 20 : mRingWidth;
			mProgress2WaterWidth = mProgress2WaterWidth == 0 ? mRingWidth * 0.6f
					: mProgress2WaterWidth;
			mRingPaint.setStrokeWidth(mRingWidth);
//			mTextPaint.setTextSize(mFontSize == 0 ? width / 5 : mFontSize);
			if (VERSION.SDK_INT== VERSION_CODES.JELLY_BEAN) {
				setLayerType(View.LAYER_TYPE_SOFTWARE, null);
			}else {
//				setLayerType(View.LAYER_TYPE_HARDWARE, null);
			}
		}

		RectF oval = new RectF();
		oval.left = mRingWidth / 2;
		oval.top = mRingWidth / 2;
		oval.right = width - mRingWidth / 2;
		oval.bottom = height - mRingWidth / 2;

		// 如果没有执行波浪动画，或者也没有指定容器宽高，就画个简单的矩形
		if ((width == 0) || (height == 0) || isInEditMode()) {
//			canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, width / 2
//					- mProgress2WaterWidth - mRingWidth, mPaintWater);
			return;
		}

		float waterPadding = mShowProgress ? mRingWidth + mProgress2WaterWidth
				: 0;
		int waterHeightCount = mShowProgress ? (int) (height - waterPadding * 2)
				: height;

		// 重新生成波浪的形状
		mWaveFactor++;
		if (mWaveFactor >= Integer.MAX_VALUE) {
			mWaveFactor = 0L;
		}

		mRingPaint.setColor(mRingBgColor);

		RectF ovallF = new RectF(mCenterPoint.x-radius, mCenterPoint.y-radius,
				mCenterPoint.x+radius, mCenterPoint.y+radius);


		mRingPaint.setColor(mRingColor);


		float waterHeight = waterHeightCount * (1 - (mCurrentProgress*1f) / mMaxProgress)
				+ waterPadding;
		int staticHeight = (int) (waterHeight + mAmplitude);

		Path mPath = new Path();
		mPath.reset();
		if (mShowProgress) {
			mPath.addCircle(width / 2, width / 2, waterHeightCount / 2,
					Direction.CCW);
		} else {
			mPath.addCircle(width / 2, width / 2, waterHeightCount / 2,
					Direction.CCW);
		}
		canvas.drawArc(ovallF, 0, 360, false, arcLinePaint);
		canvas.clipPath(mPath, Op.REPLACE);
		Paint bgPaint = new Paint();
		bgPaint.setColor(mWaterBgColor);
		canvas.drawRoundRect(new RectF(waterPadding, waterPadding, waterHeightCount
				+ waterPadding, waterHeightCount + waterPadding),0,0, bgPaint);

		canvas.drawRoundRect(new RectF(waterPadding, staticHeight, waterHeightCount
				+ waterPadding, waterHeightCount + waterPadding), 0, 0, mPaintWater);

		int xToBeDrawed = (int) waterPadding;
		int waveHeight = (int) (waterHeight - mAmplitude
				* Math.sin(Math.PI
						* (2.0F * (xToBeDrawed + (mWaveFactor * width)
								* mWaveSpeed)) / width));
		int newWaveHeight = waveHeight;
		while (true) {
			if (xToBeDrawed >= waterHeightCount + waterPadding) {
				break;
			}
			newWaveHeight = (int) (waterHeight - mAmplitude
					* Math.sin(Math.PI
							* (crestCount * (xToBeDrawed + (mWaveFactor * waterHeightCount)
									* mWaveSpeed)) / waterHeightCount));

			canvas.drawLine(xToBeDrawed, waveHeight, xToBeDrawed + 1,
					newWaveHeight, mPaintWater);

			canvas.drawLine(xToBeDrawed, newWaveHeight, xToBeDrawed + 1,
					staticHeight, mPaintWater);
			xToBeDrawed++;
			waveHeight = newWaveHeight;
		}
		if (mShowNumerical) {
			String progressTxt = (int)(mCurrentProgress*100 / mMaxProgress)
					+ "%";
			float mTxtWidth = mTextPaint.measureText(progressTxt);

			canvas.drawText(progressTxt, (getWidth() - mTextPaint.measureText(progressTxt)) / 2,
					getHeight() / 2 + mTextSize / 2-valueB, mTextPaint);
		}

	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int width = widthMeasureSpec;
		int height = heightMeasureSpec;
		width = height = (width < height) ? width : height;
		setMeasuredDimension(width, height);
	}


	public void setAmplitude(float amplitude) {
		mAmplitude = amplitude;
	}


	public void setWaterAlpha(float alpha) {
		mWaterAlpha = (int) (255.0F * alpha);
		mPaintWater.setAlpha(mWaterAlpha);
	}


	public void setWaterColor(int color) {
		mWaterColor = color;
	}


	public void setProgress(final int progress) {
		threadPool.execute(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				while (mCurrentProgress < progress) {
					mCurrentProgress += 1;

					postInvalidate();
					try {
						Thread.sleep(60);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

				}

			}
		});

	}

	public int getProgress() {
		return mProgress;
	}

	public void setWaveSpeed(float speed) {
		mWaveSpeed = speed;
	}


	public void setShowProgress(boolean b) {
		mShowProgress = b;
	}


	public void setShowNumerical(boolean b) {
		mShowNumerical = b;
	}

	public void setmRingColor(int mRingColor) {
		this.mRingColor = mRingColor;
	}


	public void setmRingBgColor(int mRingBgColor) {
		this.mRingBgColor = mRingBgColor;
	}

	public void setmWaterColor(int mWaterColor) {
		this.mWaterColor = mWaterColor;
	}


	public void setWaterBgColor(int mWaterBgColor) {
		this.mWaterBgColor = mWaterBgColor;
	}


	public void setFontSize(int mFontSize) {
		this.mFontSize = mFontSize;
	}


	public void setTextColor(int mTextColor) {
		this.mTextColor = mTextColor;
	}


	public void setMaxProgress(int mMaxProgress) {
		this.mMaxProgress = mMaxProgress;
	}


	public void setCrestCount(float crestCount) {
		this.crestCount = crestCount;
	}


	public void setRingWidth(float mRingWidth) {
		this.mRingWidth = mRingWidth;
	}

	public void setProgress2WaterWidth(float mProgress2WaterWidth) {
		this.mProgress2WaterWidth = mProgress2WaterWidth;
	}

}